package org.truenewx.tnxjee.core.config;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.bootstrap.config.PropertySourceLocator;
import org.springframework.context.ApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.truenewx.tnxjee.Framework;
import org.truenewx.tnxjee.core.util.SpringUtil;

@Order(Ordered.HIGHEST_PRECEDENCE)
public class TranslatePropertySourceLocator implements PropertySourceLocator {

    @Autowired
    private ApplicationContext context;

    @Override
    public PropertySource<?> locate(Environment environment) {
        ConfigPropertyValueTranslator translator = SpringUtil.getFirstBeanByClass(this.context,
                ConfigPropertyValueTranslator.class);
        if (translator != null) {
            Map<String, Object> properties = new HashMap<>();
            SpringUtil.loopProperties(environment, (propertyName, propertyValue) -> {
                Object translatedValue = translator.translate(propertyValue);
                if (translatedValue != null && !translatedValue.equals(propertyValue)) {
                    properties.put(propertyName, translatedValue);
                }
            });
            Map<String, PropertySourceLocator> locators = this.context.getBeansOfType(PropertySourceLocator.class);
            locators.values().forEach(locator -> {
                if (locator != this) {
                    PropertySource<?> propertySource = locator.locate(environment);
                    if (propertySource instanceof EnumerablePropertySource) {
                        EnumerablePropertySource<?> eps = (EnumerablePropertySource<?>) propertySource;
                        String[] propertyNames = eps.getPropertyNames();
                        for (String propertyName : propertyNames) {
                            Object propertyValue = eps.getProperty(propertyName);
                            Object translatedValue = translator.translate(propertyValue);
                            if (translatedValue != null && !translatedValue.equals(propertyValue)) {
                                properties.put(propertyName, translatedValue);
                            }
                        }
                    }
                }
            });
            if (!properties.isEmpty()) {
                return new MapPropertySource(Framework.NAME + "-translate", properties);
            }
        }
        return null;
    }

}
